Job Market Analysis

An overview of Lombardia job market

Data

 • Activated Contracts from Regione Lombardia

 • Ceased Contracts from Regione Lombardia

 • ATECO Code

 • GeoJSON Lombardia

In [1]:
# Retriving all datasets from online sources if we don't have them
import os
import requests

path = "./datasets/"

datasets = [
    {# Activated Contracts Dataset
        'url' : 'https://dati.lombardia.it/api/views/qbau-cyuc/rows.csv?accessType=DOWNLOAD',
        'filename' : 'Rapporti_di_lavoro_attivati.csv'
    },
    {# Ceased Contracts Dataset
        'url' : 'https://www.dati.lombardia.it/api/views/nwz3-p6vm/rows.csv?accessType=DOWNLOAD',
        'filename' : 'Rapporti_di_lavoro_cessati.csv'
    },
    {# ATECO Code Dataset
        'url' : 'https://www.istat.it/it/files//2022/03/Struttura-ATECO-2007-aggiornamento-2022.xlsx',
        'filename' : 'Struttura-ATECO-2007-aggiornamento-2022.xlsx'
    },
    {# GeoJSON border coordinates of Italy provinces from github
        'url' : 'https://dati.lombardia.it/api/views/qbau-cyuc/rows.csv?accessType=DOWNLOAD',
        'filename' : 'limits_IT_provinces.geojson'
    },   
]

# Create datasets dir
if not os.path.exists(path):
    os.mkdir(path)

# Retrive datasets
for dataset in datasets:
    if not os.path.exists(path + dataset["filename"]):
        r = requests.get(dataset["url"], allow_redirects=True)
        open(path + dataset["filename"], 'wb').write(r.content)

Data Cleaning

 • Load Datasets

 • Remove Outliers

 • Join with ATECO Code Datasets

 • Manage null values

In [39]:
df_lav_att, df_lav_ces, df_ateco, df_geojson = load_datasets()
In [40]:
plot_age_distribution(df_lav_att)
In [41]:
plot_age_distribution(df_lav_ces)
In [42]:
plot_time_distribution(df_lav_att, "Activated Contracts")
plot_time_distribution(df_lav_ces, "Ceased Contracts")

Join with ATECO Code Datasets

In [44]:
df_lav_att.groupby(['SETTOREECONOMICODETTAGLIO'])['SETTOREECONOMICODETTAGLIO'].count().to_frame()
Out[44]:
SETTOREECONOMICODETTAGLIO
SETTOREECONOMICODETTAGLIO
Acquacoltura in acqua di mare salmastra o lagunare e servizi connessi 949
Acquacoltura in acque dolci e servizi connessi 545
Affari esteri 723
Affittacamere per brevi soggiorni case ed appartamenti per vacanze bed and breakfast residence 8729
Affitto di aziende 342
... ...
Trattamento igienico del latte 984
Trivellazioni e perforazioni 1599
Università popolare 71
Utilizzo di aree forestali 1277
Villaggi turistici 906

1224 rows × 1 columns

In [46]:
df_lav_att = pd.merge(df_lav_att, df_ateco, how="left", left_on="SETTOREECONOMICODETTAGLIO", right_on="DescrizioneAteco")
df_lav_ces = pd.merge(df_lav_ces, df_ateco, how="left", left_on="SETTOREECONOMICODETTAGLIO", right_on="DescrizioneAteco")
In [47]:
df_lav_att.groupby(['MacroAteco', 'MacroDescrizione'])['MacroAteco'].count().to_frame()
Out[47]:
MacroAteco
MacroAteco MacroDescrizione
A AGRICOLTURA SILVICOLTURA E PESCA 191464
B ESTRAZIONE DI MINERALI DA CAVE E MINIERE 6122
C ATTIVITÀ MANIFATTURIERE 1683362
D FORNITURA DI ENERGIA ELETTRICA GAS VAPORE E ARIA CONDIZIONATA 11992
E FORNITURA DI ACQUA RETI FOGNARIE ATTIVITÀ DI GESTIONE DEI RIFIUTI E RISANAMENTO 30274
F COSTRUZIONI 537945
G COMMERCIO ALLINGROSSO E AL DETTAGLIO RIPARAZIONE DI AUTOVEICOLI E MOTOCICLI 976827
H TRASPORTO E MAGAZZINAGGIO 467976
I ATTIVITÀ DEI SERVIZI DI ALLOGGIO E DI RISTORAZIONE 1264749
J SERVIZI DI INFORMAZIONE E COMUNICAZIONE 713625
K ATTIVITÀ FINANZIARIE E ASSICURATIVE 66430
L ATTIVITÀ IMMOBILIARI 25336
M ATTIVITÀ PROFESSIONALI SCIENTIFICHE E TECNICHE 420783
N NOLEGGIO AGENZIE DI VIAGGIO SERVIZI DI SUPPORTO ALLE IMPRESE 869718
O AMMINISTRAZIONE PUBBLICA E DIFESA ASSICURAZIONE SOCIALE OBBLIGATORIA 87960
P ISTRUZIONE 849114
Q SANITÀ E ASSISTENZA SOCIALE 296441
R ATTIVITÀ ARTISTICHE SPORTIVE DI INTRATTENIMENTO E DIVERTIMENTO 315916
S ALTRE ATTIVITÀ DI SERVIZI 213803
T ATTIVITÀ DI FAMIGLIE E CONVIVENZE COME DATORI DI LAVORO PER PERSONALE DOMESTICO PRODUZIONE DI BENI E SERVIZI INDIFFERENZIATI PER USO PROPRIO DA PARTE DI FAMIGLIE E CONVIVENZE 348738
U ORGANIZZAZIONI ED ORGANISMI EXTRATERRITORIALI 1423

Manage null values

In [48]:
# Activated Contracts
print("Activated Contracts")
missing = df_lav_att.isnull().sum()
percent_missing = df_lav_att.isnull().sum() * 100 / len(df_lav_att)
missing_value_df = pd.DataFrame({ 'Missing': missing, 'Missing %': percent_missing })
missing_value_df
Activated Contracts
Out[48]:
Missing Missing %
DATA 0 0.000000
GENERE 0 0.000000
ETA 0 0.000000
SETTOREECONOMICODETTAGLIO 2881 0.030169
TITOLOSTUDIO 568 0.005948
CONTRATTO 0 0.000000
MODALITALAVORO 439235 4.599527
PROVINCIAIMPRESA 0 0.000000
ITALIANO 0 0.000000
CodAteco 169570 1.775682
DescrizioneAteco 169570 1.775682
MacroAteco 169570 1.775682
MacroDescrizione 169570 1.775682

Manage null values

In [49]:
# Ceased Contracts
print("Ceased Contracts")
missing = df_lav_ces.isnull().sum()
percent_missing = df_lav_ces.isnull().sum() * 100 / len(df_lav_ces)
missing_value_df = pd.DataFrame({ 'Missing': missing, 'Missing %': percent_missing })
missing_value_df
Ceased Contracts
Out[49]:
Missing Missing %
DATA 0 0.000000
GENERE 0 0.000000
ETA 0 0.000000
SETTOREECONOMICODETTAGLIO 1014 0.027346
TITOLOSTUDIO 411 0.011084
CONTRATTO 0 0.000000
MODALITALAVORO 0 0.000000
PROVINCIAIMPRESA 0 0.000000
ITALIANO 0 0.000000
CodAteco 66950 1.805542
DescrizioneAteco 66950 1.805542
MacroAteco 66950 1.805542
MacroDescrizione 66950 1.805542

Data Exploration

In [51]:
plot_diff_att_ces(df_lav_att, df_lav_ces)

Economic Sector Distribution

In [52]:
plot_ateco_live(df_lav_att)

Geographic Distrution - Activated Contracts

In [53]:
plot_geo_data(df_lav_att, df_geojson, "oranges")

Geographic Distrution - Ceased Contracts

In [54]:
plot_geo_data(df_lav_att, df_geojson, "blues")

Prediction

 • ARIMA / SARIMA

 • Prophet

 • SVR

 • MLP Regressor

 • LSTM

Train and Test Data

In [55]:
dataset = prepare_dataset(df_lav_att, df_lav_ces)
ts_actces, train, test = get_train_test(dataset, "2009-01", "2016-12", "2017-01", "2019-12")
plot_train_test(train, test)

ARIMA / SARIMA

In [56]:
arima_model = arima(ts_actces, train, test)
MAPE - Mean Absolute Percentage Error: 0.174280

Prophet

In [57]:
prophet_model = prophet(train, test)
11:58:26 - cmdstanpy - INFO - Chain [1] start processing
11:58:26 - cmdstanpy - INFO - Chain [1] done processing
MAPE - Mean Absolute Percentage Error: 0.186392

SVR

In [58]:
svr_model = svr(train, test)
MAPE - Mean Absolute Percentage Error: 0.083226

MLP Regressor

In [59]:
mlp_model = mlp(train, test)
MAPE - Mean Absolute Percentage Error: 0.128130

LSTM

In [60]:
lstm_model = lstm(train, test)
MAPE - Mean Absolute Percentage Error: 0.164999

Prediction Results

In [85]:
plot_prediction(df_plot)

Prediction Results

In [86]:
plot_prediction_and_actual(df_plot)
In [ ]:
 

Conclusions

 • Evaluation on Test data

 • Evaluation on forecasting 2020 - 2021

Improvemets

 • Work with more historical data

 • Cross Validation and Hyperparameter Tuning

Thanks for your attention!

In [ ]:
 
In [ ]: